#ifndef TABLE_H
#define TABLE_H

#include <vector>
#include <string>
#include <set>
#include <sstream>
#include <iterator>
#include "../datamanager/Data.h"
#include "../const/const.h"

class Table{
	string table_name;
	Data newTable;
	std::vector<Data> tableColumns;
	DataManager* dm;
	string str_id;
	int rank;
	int primary_key;
	set<int> indexSet;
public:
	Table(DataManager* _dm){
		dm = _dm;
		rank = 0;
		primary_key = MAX_COLUMN_NUM;
		indexSet.clear();
	}
	~Table() {}
public:
	void setName(string _name){
		table_name = _name;
		Data newTable;
		newTable.insertValue(_name);
		int table_id = dm->insertData(newTable, SYS_OBJ);
		stringstream ss;
		ss << table_id;
		ss >> str_id;
	}
	void setPrimaryKey(int key){
		primary_key = key;
		addIndex(key);
	}
	void addIndex(int index){
		indexSet.insert(index);
	}
	void addColumn(std::string name, std::string type, int length, bool canBeNull){
		Data newColumn;
		newColumn.insertValue(str_id);
		newColumn.insertValue(name);
		newColumn.insertValue(type);
		newColumn.insertValue(Data::intZip(length,MAX_COLUMN_LENGTH));
		string r = "";
		++rank;
		r += char(rank);
		newColumn.insertValue(r);
		if(canBeNull) newColumn.insertValue("1");
		else newColumn.insertValue("0");
		tableColumns.push_back(newColumn);
	}
	void create(){
		int index;
		for(int i = 0; i < tableColumns.size(); ++i)
			dm->insertData(tableColumns[i], SYS_COLUMN);
		BufType buf = dm->getBpm()->getPage(dm->getFileID(), FIRST_DATABASE_PAGE, index);
		dm->getBpm()->markDirty(index);
		Data newTableIndex;
		int page_id = buf[DATABASE_PAGE_NEXT_EMPTY_PAGE];
		buf[DATABASE_PAGE_NEXT_EMPTY_PAGE] += 2;
		newTableIndex.insertValue(str_id);
		newTableIndex.insertValue(Data::intZip(page_id,MAX_TABLE_INDEX));
		newTableIndex.insertValue(Data::intZip(primary_key,MAX_TABLE_KEY));
		int has_index = 0;
		set<int>::iterator it;
		newTableIndex.insertValue(Data::intZip(has_index,MAX_TABLE_HAS_INDEX));
		dm->insertData(newTableIndex, SYS_INDEX);
		buf = dm->getBpm()->getPage(dm->getFileID(), page_id, index);
		dm->getBpm()->markDirty(index);
		buf[PAGE_HEAD_INFO] = 0;
		buf[PAGE_HEAD_NEXT_PAGE] = 1 << 30;
		buf[PAGE_HEAD_DATA_NUM] = 0;
		for(int i = PAGE_HEAD_IN_USE; i < PAGE_HEAD_LEN; ++i)
			buf[i] = 0;
		buf = dm->getBpm()->getPage(dm->getFileID(), page_id + 1, index);
		dm->getBpm()->markDirty(index);
		buf[INDEX_PAGE_NUM] = 0;
		for(it = indexSet.begin(); it != indexSet.end(); ++it)
			dm->addIndex(table_name, *it);
	}
};

#endif // TABLE_H
